package com.sky.service.admin.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.sky.constant.MessageConstant;
import com.sky.constant.StatusConstant;
import com.sky.dto.DishDTO;
import com.sky.dto.DishPageQueryDTO;
import com.sky.exception.DataException;
import com.sky.exception.DeletionNotAllowedException;
import com.sky.mapper.common.DishFlavorMapper;
import com.sky.mapper.common.DishMapper;
import com.sky.mapper.common.SetmealDishMapper;
import com.sky.pojo.Dish;
import com.sky.pojo.DishFlavor;
import com.sky.result.PageResult;
import com.sky.result.Result;
import com.sky.service.admin.DishService;
import com.sky.vo.DishVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;

@Service
@Transactional(readOnly = true)
public class DishServiceImpl implements DishService {
    private final String USER_DISH_CACHE = "dish_";

    @Autowired
    private DishMapper dishMapper;

    @Autowired
    private DishFlavorMapper dishFlavorMapper;

    @Autowired
    private SetmealDishMapper setmealDishMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 新增菜品
     *
     * @param dto
     * @return
     */
    @Override
    @Transactional(readOnly = false)
    public Result<String> save(DishDTO dto) throws CloneNotSupportedException {
        //1. 拷贝dto的数据到pojo
        Dish dish = dto.clone();

        //2. 新增菜品数据-返回新增的菜品id
        dishMapper.insert(dish);

        //3. 使用批量添加的方式-新增口味数据
        dto.getFlavors().forEach(dishFlavor -> dishFlavor.setDishId(dish.getId()));

        dishFlavorMapper.batchInert(dto.getFlavors());

        //过期对应菜品的缓存数据
        cleanCache(USER_DISH_CACHE + dish.getCategoryId());

        return Result.success();
    }

    /**
     * 根据条件分页查询菜品数据
     *
     * @param queryDto
     * @return
     */
    @Override
    public Result<PageResult> page(DishPageQueryDTO queryDto) {
        //1. 校验分页参数

        //2. 设置分页参数
        PageHelper.startPage(queryDto.getPage(), queryDto.getPageSize());

        //3. 调用mapper完成数据的查询
        Dish dish = new Dish();
        BeanUtils.copyProperties(queryDto, dish);

        Page<DishVO> page = dishMapper.selectByPage(dish);

        //4. 封装结果
        PageResult pageResult = new PageResult();
        pageResult.setRecords(page.getResult());
        pageResult.setTotal(page.getTotal());

        return Result.success(pageResult);
    }

    /**
     * 根据id批量删除菜品
     *
     * @param ids
     * @return
     */
    @Override
    @Transactional(readOnly = false)
    public Result<String> delete(List<Long> ids) {
        //1. 判断集合的id是否为空 如果为空则抛出异常
        if(null == ids || ids.size() == 0){
            throw new DataException(MessageConstant.DATA_ERROR);
        }

        //2. 判断要删除的菜品中是否有在售的商品 如果有则抛出异常
        int count = dishMapper.selectCountByIdsAndStatus(ids);
        if(count > 0){
            throw new DeletionNotAllowedException(MessageConstant.DISH_ON_SALE);
        }

        //3. 判断要删除的菜品中是否有在套餐中关联了,如果关联了套餐则抛出异常
        count = setmealDishMapper.selectCountByDishIds(ids);
        if(count > 0){
            throw new DeletionNotAllowedException(MessageConstant.DISH_BE_RELATED_BY_SETMEAL);
        }

        //4. 批量删除菜品数据
        dishMapper.deleteByIds(ids);

        //5. 批量删除口味数据
        dishFlavorMapper.deleteByIds(ids);

        //删除缓存数据- 因为批量删除可能会删除N个分类下的商品 此时我们可以过期所有分类的数据
        cleanCache(USER_DISH_CACHE + "*");

        //6. 返回结果
        return Result.success();
    }

    /**
     * 根据菜品的id查询菜品信息和口味数据
     *
     * @param dishId
     * @return
     */
    @Override
    public Result<DishVO> getById(Long dishId) {
        DishVO vo = dishMapper.selectById(dishId);
        return Result.success(vo);
    }

    /**
     * 根据id修改菜品的数据
     *
     * @param dto
     * @return
     */
    @Override
    @Transactional(readOnly = false)
    public Result<String> update(DishDTO dto) {
        //1. 更新菜品数据
        Dish dish = new Dish();
        BeanUtils.copyProperties(dto, dish);
        dishMapper.updateById(dish);

        //2. 更新口味数据- 对于关联关系 如果不太好维护的 那么我们都建议先删除关系 然后在重写插入关系
        //2.1 通过菜品id删除口味数据
        dishFlavorMapper.deleteByIds(Arrays.asList(dto.getId()));

        //2.2 批量插入菜品的口味数据
        dto.getFlavors().forEach(dishFlavor -> dishFlavor.setDishId(dto.getId()));

        dishFlavorMapper.batchInert(dto.getFlavors());

        //过期对应菜品的缓存数据
        cleanCache(USER_DISH_CACHE + dish.getCategoryId());

        return Result.success();
    }

    /**
     * 根据分类id查询菜品
     * @param categoryId
     * @return
     */
    public List<Dish> list(Long categoryId) {
        Dish dish = Dish.builder()
                .categoryId(categoryId)
                .status(StatusConstant.ENABLE)
                .build();
        return dishMapper.list(dish);
    }

    /**
     * 条件查询菜品和口味
     * @param dish
     * @return
     */
    public List<DishVO> listWithFlavor(Dish dish) {
        List<Dish> dishList = dishMapper.list(dish);

        List<DishVO> dishVOList = new ArrayList<>();

        for (Dish d : dishList) {
            DishVO dishVO = new DishVO();
            BeanUtils.copyProperties(d,dishVO);

            //根据菜品id查询对应的口味
            List<DishFlavor> flavors = dishFlavorMapper.getByDishId(d.getId());

            dishVO.setFlavors(flavors);
            dishVOList.add(dishVO);
        }

        return dishVOList;
    }

    private void cleanCache(String key){
        Set set = redisTemplate.keys(key);
        redisTemplate.delete(set);
    }
}
